{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 第三节 线性代数与NumPy"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 1. 模块与包"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 模块：以.py结尾的Python源代码文件\n",
    "- NumPy\n",
    "- sys\n",
    "- time\n",
    "- ......"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 包：模块的集合"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![](module-package.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 2. NumPy的导入"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np    # 导入NumPy模块"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1.17.2\n"
     ]
    }
   ],
   "source": [
    "print(np.version.version)   # 查看当前安装的NumPy的版本"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. NumPy的基本数据结构"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2 3]\n",
      " [4 5 6]]\n"
     ]
    }
   ],
   "source": [
    "a = np.array([[1, 2, 3], [4, 5, 6]])   # NumPy中基本数据类型-数组的声明\n",
    "print(a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "数组a的维度个数为:  2\n"
     ]
    }
   ],
   "source": [
    "print(\"数组a的维度个数为: \", a.ndim)  # 数组的维度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "数组a的各个维度长度为:  (2, 3)\n"
     ]
    }
   ],
   "source": [
    "print(\"数组a的各个维度长度为: \", a.shape)  # 数组各个维度的长度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "数组a中元素总数为:  6\n"
     ]
    }
   ],
   "source": [
    "print(\"数组a中元素总数为: \", a.size)  # 数组里元素总数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "数组a中元素类型为:  int64\n"
     ]
    }
   ],
   "source": [
    "print(\"数组a中元素类型为: \", a.dtype)  # 数组元素的类型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 0  5 10 15]\n"
     ]
    }
   ],
   "source": [
    "b = np.arange(0, 20, 5)     # 用arange函数创建数组 (开始值，终值，步长)\n",
    "print(b)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 0,  5],\n",
       "       [10, 15]])"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "b.reshape(2, 2)         # 改变数组的形状"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.         0.22222222 0.44444444 0.66666667 0.88888889 1.11111111\n",
      " 1.33333333 1.55555556 1.77777778 2.        ]\n"
     ]
    }
   ],
   "source": [
    "c = np.linspace(0, 2, 10)   # 用linspace函数创建数组（开始值，终值，元素个数）\n",
    "print(c)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]\n",
      " [0. 0. 0. 0.]]\n"
     ]
    }
   ],
   "source": [
    "zero_arr = np.zeros((3,4))   # 快速创建元素全为0的数组\n",
    "print(zero_arr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[[1 1 1 1]\n",
      "  [1 1 1 1]\n",
      "  [1 1 1 1]]\n",
      "\n",
      " [[1 1 1 1]\n",
      "  [1 1 1 1]\n",
      "  [1 1 1 1]]]\n"
     ]
    }
   ],
   "source": [
    "one_arr = np.ones((2,3,4), dtype=np.int64)   # 快速创建元素全为1的数组，并将类型设置为整型\n",
    "print(one_arr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1. 0. 0.]\n",
      " [0. 1. 0.]\n",
      " [0. 0. 1.]]\n"
     ]
    }
   ],
   "source": [
    "eye_arr = np.eye(3)   # 快速创建对角阵 \n",
    "print(eye_arr)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 4. NumPy数组的切片和索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 2 3 4]\n",
      "[1 3]\n"
     ]
    }
   ],
   "source": [
    "arr = np.array([1, 2, 3, 4, 5, 6])\n",
    "print(arr[0:4])      \n",
    "print(arr[0:4:2])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "5\n",
      "6\n"
     ]
    }
   ],
   "source": [
    "for ele in arr:     # 对数组中每个元素的遍历\n",
    "    print(ele)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2 3]\n",
      " [4 5 6]]\n"
     ]
    }
   ],
   "source": [
    "arr = arr.reshape(2,3)     # 更改arr数组的形状\n",
    "print(arr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 2 3]\n"
     ]
    }
   ],
   "source": [
    "print(arr[0,:])            # 在arr数组里选择第一维度的第一个子序列，"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n"
     ]
    }
   ],
   "source": [
    "print(arr[0, 0])           # 在arr数组里选择第一维度的第一个子序列里的第一个元素"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[2 5]\n"
     ]
    }
   ],
   "source": [
    "print(arr[:, 1])           # 在arr数组里选择第二维度的第二个子序列里的所有元素"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 5. NumPy数组的基本操作"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2]\n",
      " [3 4]]\n",
      "********\n",
      "[[5 6]\n",
      " [7 8]]\n"
     ]
    }
   ],
   "source": [
    "arr1 = np.array([[1, 2], [3, 4]])     # 声明两个二维数组\n",
    "print(arr1)\n",
    "print(\"********\")\n",
    "arr2 = np.array([[5, 6], [7, 8]])\n",
    "print(arr2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[4 4]\n",
      " [4 4]]\n"
     ]
    }
   ],
   "source": [
    "print(arr2-arr1)     # 两个数组元素级别的差运算"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 6  8]\n",
      " [10 12]]\n"
     ]
    }
   ],
   "source": [
    "print(arr2+arr1)     # 两个数组元素级别的和运算"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 5 12]\n",
      " [21 32]]\n"
     ]
    }
   ],
   "source": [
    "print(arr2*arr1)     # 两个数组元素级别的乘运算"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[5.         3.        ]\n",
      " [2.33333333 2.        ]]\n"
     ]
    }
   ],
   "source": [
    "print(arr2/arr1)     # 两个数组元素级别的除运算"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[ 1  4]\n",
      " [ 9 16]]\n"
     ]
    }
   ],
   "source": [
    "print(arr1**2)     # 数组元素级别的乘方运算 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[19 22]\n",
      " [43 50]]\n"
     ]
    }
   ],
   "source": [
    "print(arr1@arr2)     # 两个数组之间的矩阵乘积运算"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[19 22]\n",
      " [43 50]]\n",
      "**********\n",
      "[[19 22]\n",
      " [43 50]]\n"
     ]
    }
   ],
   "source": [
    "print(np.dot(arr1, arr2))   # 使用dot进行的两个数组之间的矩阵乘积运算\n",
    "print(\"*\" * 10)\n",
    "print(arr1.dot(arr2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 3]\n",
      " [2 4]]\n"
     ]
    }
   ],
   "source": [
    "print(arr1.T)      # 数组的转置"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 61,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2 3]\n",
      " [4 5 6]]\n",
      "arr1中最大元素的索引为:  5\n",
      "arr1中沿第一个轴最大元素的索引为:  [1 1 1]\n",
      "arr1中沿第二个轴最大元素的索引为:  [2 2]\n"
     ]
    }
   ],
   "source": [
    "arr3 = np.array([[1, 2, 3], [4, 5, 6]])\n",
    "print(arr3)\n",
    "print(\"arr1中最大元素的索引为: \", np.argmax(arr3))                    # 数组中值最大元素的索引\n",
    "print(\"arr1中沿第一个轴最大元素的索引为: \", np.argmax(arr3, axis=0))    # 数组中沿第一个维度值最大元素的索引\n",
    "print(\"arr1中沿第二个轴最大元素的索引为: \", np.argmax(arr3, axis=1))    # 数组中沿第二个维度值最大元素的索引"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 6. NumPy求解线性方程组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Array形式的a形状为： (2,)\n",
      "Matrix形式的a形状为： (1, 2)\n"
     ]
    }
   ],
   "source": [
    "# NumPy中array与matrix的异同\n",
    "import numpy as np\n",
    "a_arr = np.array([1,2])\n",
    "print(\"Array形式的a形状为：\", a_arr.shape)\n",
    "a_mat = np.mat([1,2])\n",
    "print(\"Matrix形式的a形状为：\", a_mat.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "此矩阵为：\n",
      " [[1 2]\n",
      " [3 4]]\n",
      "**********\n",
      "此矩阵的转置为：\n",
      " [[1 3]\n",
      " [2 4]]\n"
     ]
    }
   ],
   "source": [
    "# 得到矩阵的转置\n",
    "mat_temp = np.mat([[1,2],[3,4]])\n",
    "print(\"此矩阵为：\\n\", mat_temp)\n",
    "print('*' * 10)\n",
    "print(\"此矩阵的转置为：\\n\", mat_temp.T)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "此矩阵为：\n",
      " [[1 2]\n",
      " [3 4]]\n",
      "**********\n",
      "此矩阵的逆矩阵为：\n",
      " [[-2.   1. ]\n",
      " [ 1.5 -0.5]]\n",
      "此矩阵与它的逆矩阵相乘得到：\n",
      " [[1. 0.]\n",
      " [0. 1.]]\n"
     ]
    }
   ],
   "source": [
    "# 得到矩阵的逆\n",
    "mat_temp = np.mat([[1,2],[3,4]])\n",
    "print(\"此矩阵为：\\n\", mat_temp)\n",
    "print('*' * 10)\n",
    "mat_inv = mat_temp.I\n",
    "print(\"此矩阵的逆矩阵为：\\n\", mat_inv)\n",
    "print(\"此矩阵与它的逆矩阵相乘得到：\\n\", np.round(mat_temp.dot(mat_inv)))    # np.round用来保留结果到指定位数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "此线性方程组为：\n",
      " [[1 2 3]\n",
      " [4 5 6]]\n",
      "**********\n",
      "此线性方程组的解为：\n",
      " [[-1.]\n",
      " [ 2.]]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "equa = np.mat([[1,2,3],[4,5,6]])\n",
    "print(\"此线性方程组为：\\n\", equa)\n",
    "print('*' * 10)\n",
    "A = np.array([[1,2], [4,5]])   # 2x2系数矩阵\n",
    "b = np.array([3,6])            # 2x1矩阵\n",
    "res = np.linalg.solve(A,b)     # 求解该系数矩阵决定的线性方程组\n",
    "print(\"此线性方程组的解为：\\n\", res.reshape(1,2).T)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "此线性方程组为：\n",
      " [[1 2 3]\n",
      " [4 5 6]]\n",
      "**********\n",
      "此线性方程组的解为：\n",
      " [[-1.]\n",
      " [ 2.]]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "equa = np.mat([[1,2,3],[4,5,6]])\n",
    "print(\"此线性方程组为：\\n\", equa)\n",
    "print('*' * 10)\n",
    "A = np.mat([[1,2], [4,5]])   # 2x2系数矩阵\n",
    "b = np.mat([3,6]).T  # 2x1矩阵(须为列向量的形式)\n",
    "res = np.linalg.solve(A,b)   # 求解该系数矩阵决定的线性方程组\n",
    "print(\"此线性方程组的解为：\\n\", res)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
